package com.surfilter.gsxt.crawler;

import com.surfilter.gsxt.OprateException;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Driver使用完之后必须归还,否则会资源泄露,最终导致没有可用的Driver
 * 
 * @author root
 *
 */
public class PhantomJSDriverPools {
	
	private static final Logger logger = LoggerFactory.getLogger(PhantomJSDriverPools.class);

	private static List<PhantomJSDriverManager> drivers = new ArrayList<PhantomJSDriverManager>();
	
	private static PhantomJSDriverPools pools = new PhantomJSDriverPools();
	
	private static Long time_out = 1 * 60 * 60l;

	private static ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
	
	static{
		 Runnable runnable = new Runnable() {  
	            public void run() {  
	                // task to run goes here
					logger.info("phantomjs线程跟踪器启动");
	            	clearPhantomJSDrivers(time_out * 500);
	            	system_pools_info();
	            }
		 };
		 service.scheduleAtFixedRate(runnable, 10, time_out, TimeUnit.SECONDS);
	}
	
	public static PhantomJSDriverPools single(){
		return pools;
	}
	
	public static void initDriverPools(int pool_length){
		if(pool_length <= 0)pool_length = 1;
		logger.info("开始初始化PhontomJs线程池,初始化个数：{}", pool_length);
		synchronized (drivers) {
			if(drivers.size() < pool_length){
				createPhantomJSDriver(pool_length - drivers.size());
			}			
		}
		logger.info("初始化PhontomJs线程池完成,初始化可用个数：{}", drivers.size());
	}
	
	public static PhantomJSDriver getPhantomJSDriver() throws OprateException {
		PhantomJSDriver result = null;
		if(drivers == null){
			throw new OprateException("请先初始化线程池");
		}
		synchronized (drivers) {
			Collections.sort(drivers);
			for(PhantomJSDriverManager driver : drivers){
				if(!driver.isUse()){
					result = driver.getDriver();
					driver.setUse(true);
					driver.setUseTime(System.currentTimeMillis());
					break;
				}
			}
		}
		return result;
	}
	
	public static PhantomJSDriver getPhantomJSDriver(Long time_out) throws OprateException, InterruptedException{
		PhantomJSDriver result = null;
		Long start = System.currentTimeMillis();
		Long end = start;
		while(end - start < time_out){
			result = getPhantomJSDriver();
			if(result != null)break;
			Thread.sleep(3000);
			end = System.currentTimeMillis();
		}
		return result;
	}
	
	public static void reopenPhantomJSDriver(PhantomJSDriver driver){
		if(driver == null){
			return;
		}
		String session = driver.getSessionId().toString();
		synchronized (drivers) {
			for(PhantomJSDriverManager driver_r : drivers){
				if(driver_r.getSessionId().equalsIgnoreCase(session)){
					driver_r.reopenDriver();
				}
			}
		}
	}
	
	public static void returnPhantomJSDriver(PhantomJSDriver driver) throws OprateException{
		if(driver == null){
			throw new OprateException("请提供有效参数");
		}
		String session = driver.getSessionId().toString();
		synchronized (drivers) {
			for(PhantomJSDriverManager driver_r : drivers){
				if(driver_r.getSessionId().equalsIgnoreCase(session)){
					driver_r.setUse(false);
					driver_r.score();
				}
			}
		}
	}
	
	private static void clearPhantomJSDrivers(Long time_out){
		if(drivers == null || drivers.size() == 0)return;
		Long this_time = System.currentTimeMillis();
		synchronized (drivers) {
			for(PhantomJSDriverManager driver_r : drivers){
				if(driver_r.isUse()){
					if(this_time - driver_r.getUseTime() > time_out){
						driver_r.reopenDriver();
						driver_r.setUse(false);
					}
				}
//				else{
//					driver_r.reopenDriver();
//				}
			}
		}
	}
	
	private static void system_pools_info(){
		int pools_size = 0;
		int pools_using = 0;
		
		synchronized (drivers) {
			pools_size = drivers.size();
			for(PhantomJSDriverManager driver : drivers){
				if(driver.isUse())pools_using ++;
			}
		}
		
		logger.info("pools_size:{},pools_using:{}", pools_size, pools_using);
	}
	
	private static void createPhantomJSDriver(int create_num){
		for(int i = 0 ; i < create_num; i ++){
			PhantomJSDriverManager driverM = new PhantomJSDriverManager();
			driverM.reopenDriver();
			drivers.add(driverM);
		}
	}
	
	private PhantomJSDriverPools(){}
	
	public static void main(String[] args) {
		try{
			throw new org.openqa.selenium.remote.UnreachableBrowserException("");
		}catch(Exception e){
			
		}finally{
			System.out.println("123123123");
		}
	}
	
}
